package day_02_ThreadCommunicate;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 资源类--阳哥的方式【使用并发编程类 Lock 和 Condition 来替换 synchronize 和 wait、notify】
 */
class MyResourceCorrectWay{

    private int number = 0;
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();

    /**
     * 1、使用
     * ----------------------
     * lock.lock()
     * try{
     *     //xxx
     * } catch(Exception e){
     *
     * } finally{
     *     lock.unlock();
     * }
     * ----------------------
     * 来替代 synchronize(){
     *     //xxx
     * }
     * ----------------------
     * 2、使用 condition.await() 替代 wait，condition.signal() 替代 notify；
     */
    public /*synchronized*/ void increment() {
        lock.lock();
        try{
            // 1、判断
            while (number != 0){
                try {
                    //this.wait();
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 2、干活
            number++;
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            // 3、通知
            //this.notifyAll();
            condition.signalAll();
        } catch(Exception e){
            e.printStackTrace();
        } finally{
            lock.unlock();
        }
    }

    public /*synchronized*/ void decrement() {
        lock.lock();
        try{
            // 1、判断
            while (number == 0){
                try {
                    //this.wait();
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 2、干活
            number--;
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            // 3、通知
            //this.notifyAll();
            condition.signalAll();
        } catch(Exception e){
            e.printStackTrace();
        } finally{
            lock.unlock();
        }
    }

}

/*
class MyResourceCorrectWay{

    private int number = 0;

    public synchronized void increment() {
        // 1、判断
        while (number != 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 2、干活
        number++;
        System.out.println(Thread.currentThread().getName() + "\t" + number);
        // 3、通知
        this.notifyAll();
    }

    public synchronized void decrement() {
        // 1、判断
        while (number == 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 2、干活
        number--;
        System.out.println(Thread.currentThread().getName() + "\t" + number);
        // 3、通知
        this.notifyAll();
    }

}
*/

/**
 *【总结--多线程操作最终的三个口诀】：
 * 1、高内聚低耦合，线程操作资源类
 * 2、判断/干活/通知
 * 3、多线程交互场景（即wait和notify），必须要防止虚假唤醒，此时判断只用while，不用if
 */

/**
 * @Description 线程间通信--四个线程交替操作资源类【方式三：最终正确的版本】
 * @Author shihan
 * @Date 2020/10/31 15:03
 * @Version 1.0
 */
public class ThreadWaitNotifyDemoCorrectWay {

    /**
     * 实现四个线程交替操作：
     * 线程A、C将数 +1，线程B、D将数 -1，交替执行10轮
     * @param args
     */
    public static void main(String[] args) {
        MyResourceCorrectWay myResourceCorrectWay = new MyResourceCorrectWay();

        new Thread(() -> { for (int i = 0; i < 10; i++)  myResourceCorrectWay.increment(); },"线程A").start();
        new Thread(() -> { for (int i = 0; i < 10; i++)  myResourceCorrectWay.decrement(); },"线程B").start();

        new Thread(() -> { for (int i = 0; i < 10; i++)  myResourceCorrectWay.increment(); },"线程C").start();
        new Thread(() -> { for (int i = 0; i < 10; i++)  myResourceCorrectWay.decrement(); },"线程D").start();

    }
}
